// DbCreate.cpp
#include "DbCreate.h"
#include <iostream>
#include <sstream>
#include <string>
#include <map>
#include <vector>

// --- 工具函数：将 repeated string 转换为分隔符分隔的字符串 ---
std::string join_repeated_strings(const ::google::protobuf::RepeatedPtrField<std::string>& repeated_field, const std::string& delimiter = ";") {
    std::ostringstream oss;
    bool first = true;
    for (const auto& s : repeated_field) {
        if (!first) oss << delimiter;
        oss << s;
        first = false;
    }
    return oss.str();
}

// --- 辅助函数：构建neo4j参数值 ---
neo4j_value_t create_params_from_map(const std::map<std::string, neo4j_value_t>& params_map) {
    if (params_map.empty()) {
        return neo4j_map(NULL, 0);
    }
    
    std::vector<neo4j_map_entry_t> entries;
    entries.reserve(params_map.size());
    
    for (const auto& pair : params_map) {
        entries.push_back({ 
            .key = neo4j_string(pair.first.c_str()), 
            .value = pair.second 
        });
    }
    
    return neo4j_map(entries.data(), entries.size());
}

// --- 辅助函数：创建各种类型的neo4j值 ---
neo4j_value_t create_neo4j_string(const std::string& str) {
    return neo4j_string(str.c_str());
}

neo4j_value_t create_neo4j_int(int64_t value) {
    return neo4j_int(value);
}

neo4j_value_t create_neo4j_bool(bool value) {
    return neo4j_bool(value);
}

neo4j_value_t create_neo4j_float(double value) {
    return neo4j_float(value);
}

neo4j_value_t create_neo4j_null() {
    return neo4j_null;
}

// --- 节点创建方法 ---

bool DbCreate::CreateUser(const ::graph::UserNode& user_node, std::string& error_message) {
    try {
        // 1. 准备属性参数映射
        std::map<std::string, neo4j_value_t> props;
        props["id"] = create_neo4j_int(user_node.id());
        props["username"] = create_neo4j_string(user_node.username());
        props["email"] = create_neo4j_string(user_node.email());
        props["password_hash"] = create_neo4j_string(user_node.password_hash());
        props["created_at"] = create_neo4j_string(user_node.created_at());
        props["updated_at"] = create_neo4j_string(user_node.updated_at());
        props["age_group"] = create_neo4j_string(user_node.age_group());
        props["gender"] = create_neo4j_string(user_node.gender());
        props["location"] = create_neo4j_string(user_node.location());
        props["activity_level"] = create_neo4j_string(user_node.activity_level());
        props["interests_str"] = create_neo4j_string(join_repeated_strings(user_node.interests()));

        // 2. 构建 Cypher 查询
        std::ostringstream cypher_oss;
        cypher_oss << "CREATE (n:User {";
        bool first = true;
        for (const auto& prop_pair : props) {
            if (!first) cypher_oss << ", ";
            cypher_oss << prop_pair.first << ": $" << prop_pair.first;
            first = false;
        }
        cypher_oss << "}) RETURN n";
        const std::string cypher_query = cypher_oss.str();

        // 3. 创建参数值
        neo4j_value_t params = create_params_from_map(props);

        // 4. 执行查询
        DbClient& db_client = DbClient::getInstance();
        neo4j_result_stream_t* result = db_client.run(cypher_query.c_str(), params);
        
        if (result == NULL) {
            error_message = "Failed to execute CreateUser query";
            std::cerr << error_message << std::endl;
            return false;
        }

        // 释放结果流
        neo4j_close_results(result);

        std::cout << "Successfully created User node with ID: " << user_node.id() << std::endl;
        return true;

    } catch (const std::exception& e) {
        error_message = "CreateUser failed: ";
        error_message += e.what();
        std::cerr << error_message << std::endl;
        return false;
    } catch (...) {
        error_message = "CreateUser failed: Unknown error occurred.";
        std::cerr << error_message << std::endl;
        return false;
    }
}

bool DbCreate::CreateList(const ::graph::ListNode& list_node, std::string& error_message) {
    try {
        // 1. 准备属性参数映射
        std::map<std::string, neo4j_value_t> props;
        props["id"] = create_neo4j_int(list_node.id());
        props["user_id"] = create_neo4j_int(list_node.user_id());
        props["title"] = create_neo4j_string(list_node.title());
        props["is_urgent"] = create_neo4j_bool(list_node.is_urgent());
        props["is_collaborative"] = create_neo4j_bool(list_node.is_collaborative());
        props["priority"] = create_neo4j_string(list_node.priority());
        props["location_scope"] = create_neo4j_string(list_node.location_scope());
        props["publish_date"] = create_neo4j_string(list_node.publish_date());
        props["start_time"] = create_neo4j_string(list_node.start_time());
        props["end_time"] = create_neo4j_string(list_node.end_time());
        props["is_public"] = create_neo4j_bool(list_node.is_public());
        props["view_count"] = create_neo4j_int(list_node.view_count());
        props["like_count"] = create_neo4j_int(list_node.like_count());
        props["comment_count"] = create_neo4j_int(list_node.comment_count());
        props["created_at"] = create_neo4j_string(list_node.created_at());
        props["updated_at"] = create_neo4j_string(list_node.updated_at());
        props["category"] = create_neo4j_string(list_node.category());
        props["tags_str"] = create_neo4j_string(join_repeated_strings(list_node.tags()));

        // 2. 构建 Cypher 查询
        std::ostringstream cypher_oss;
        cypher_oss << "CREATE (n:List {";
        bool first = true;
        for (const auto& prop_pair : props) {
            if (!first) cypher_oss << ", ";
            cypher_oss << prop_pair.first << ": $" << prop_pair.first;
            first = false;
        }
        cypher_oss << "}) RETURN n";
        const std::string cypher_query = cypher_oss.str();

        // 3. 创建参数值
        neo4j_value_t params = create_params_from_map(props);

        // 4. 执行查询
        DbClient& db_client = DbClient::getInstance();
        neo4j_result_stream_t* result = db_client.run(cypher_query.c_str(), params);
        
        if (result == NULL) {
            error_message = "Failed to execute CreateList query";
            std::cerr << error_message << std::endl;
            return false;
        }

        // 释放结果流
        neo4j_close_results(result);

        std::cout << "Successfully created List node with ID: " << list_node.id() << std::endl;
        return true;

    } catch (const std::exception& e) {
        error_message = "CreateList failed: ";
        error_message += e.what();
        std::cerr << error_message << std::endl;
        return false;
    } catch (...) {
        error_message = "CreateList failed: Unknown error occurred.";
        std::cerr << error_message << std::endl;
        return false;
    }
}

bool DbCreate::CreateTodo(const ::graph::TodoNode& todo_node, std::string& error_message) {
    try {
        // 1. 准备属性参数映射
        std::map<std::string, neo4j_value_t> props;
        props["id"] = create_neo4j_int(todo_node.id());
        props["list_id"] = create_neo4j_int(todo_node.list_id());
        props["content"] = create_neo4j_string(todo_node.content());
        props["is_completed"] = create_neo4j_bool(todo_node.is_completed());
        props["sort_order"] = create_neo4j_int(todo_node.sort_order());
        props["created_at"] = create_neo4j_string(todo_node.created_at());
        props["category"] = create_neo4j_string(todo_node.category());
        props["tags_str"] = create_neo4j_string(join_repeated_strings(todo_node.tags()));

        // 2. 构建 Cypher 查询
        std::ostringstream cypher_oss;
        cypher_oss << "CREATE (n:Todo {";
        bool first = true;
        for (const auto& prop_pair : props) {
            if (!first) cypher_oss << ", ";
            cypher_oss << prop_pair.first << ": $" << prop_pair.first;
            first = false;
        }
        cypher_oss << "}) RETURN n";
        const std::string cypher_query = cypher_oss.str();

        // 3. 创建参数值
        neo4j_value_t params = create_params_from_map(props);

        // 4. 执行查询
        DbClient& db_client = DbClient::getInstance();
        neo4j_result_stream_t* result = db_client.run(cypher_query.c_str(), params);
        
        if (result == NULL) {
            error_message = "Failed to execute CreateTodo query";
            std::cerr << error_message << std::endl;
            return false;
        }

        // 释放结果流
        neo4j_close_results(result);

        std::cout << "Successfully created Todo node with ID: " << todo_node.id() << std::endl;
        return true;

    } catch (const std::exception& e) {
        error_message = "CreateTodo failed: ";
        error_message += e.what();
        std::cerr << error_message << std::endl;
        return false;
    } catch (...) {
        error_message = "CreateTodo failed: Unknown error occurred.";
        std::cerr << error_message << std::endl;
        return false;
    }
}

bool DbCreate::CreateComment(const ::graph::CommentNode& comment_node, std::string& error_message) {
    try {
        // 1. 准备属性参数映射
        std::map<std::string, neo4j_value_t> props;
        props["id"] = create_neo4j_int(comment_node.id());
        props["list_id"] = create_neo4j_int(comment_node.list_id());
        props["user_id"] = create_neo4j_int(comment_node.user_id());
        props["content"] = create_neo4j_string(comment_node.content());
        props["created_at"] = create_neo4j_string(comment_node.created_at());

        // 2. 构建 Cypher 查询
        std::ostringstream cypher_oss;
        cypher_oss << "CREATE (n:Comment {";
        bool first = true;
        for (const auto& prop_pair : props) {
            if (!first) cypher_oss << ", ";
            cypher_oss << prop_pair.first << ": $" << prop_pair.first;
            first = false;
        }
        cypher_oss << "}) RETURN n";
        const std::string cypher_query = cypher_oss.str();

        // 3. 创建参数值
        neo4j_value_t params = create_params_from_map(props);

        // 4. 执行查询
        DbClient& db_client = DbClient::getInstance();
        neo4j_result_stream_t* result = db_client.run(cypher_query.c_str(), params);
        
        if (result == NULL) {
            error_message = "Failed to execute CreateComment query";
            std::cerr << error_message << std::endl;
            return false;
        }

        // 释放结果流
        neo4j_close_results(result);

        std::cout << "Successfully created Comment node with ID: " << comment_node.id() << std::endl;
        return true;

    } catch (const std::exception& e) {
        error_message = "CreateComment failed: ";
        error_message += e.what();
        std::cerr << error_message << std::endl;
        return false;
    } catch (...) {
        error_message = "CreateComment failed: Unknown error occurred.";
        std::cerr << error_message << std::endl;
        return false;
    }
}

bool DbCreate::CreateEntity(const ::graph::EntityNode& entity_node, std::string& error_message) {
    try {
        // 1. 准备属性参数映射
        std::map<std::string, neo4j_value_t> props;
        props["id"] = create_neo4j_string(entity_node.id());
        props["name"] = create_neo4j_string(entity_node.name());
        props["type"] = create_neo4j_string(entity_node.type());
        props["category"] = create_neo4j_string(entity_node.category());
        props["popularity_score"] = create_neo4j_float(entity_node.popularity_score());
        props["created_at"] = create_neo4j_string(entity_node.created_at());

        // 2. 构建 Cypher 查询
        std::ostringstream cypher_oss;
        cypher_oss << "CREATE (n:Entity {";
        bool first = true;
        for (const auto& prop_pair : props) {
            if (!first) cypher_oss << ", ";
            cypher_oss << prop_pair.first << ": $" << prop_pair.first;
            first = false;
        }
        cypher_oss << "}) RETURN n";
        const std::string cypher_query = cypher_oss.str();

        // 3. 创建参数值
        neo4j_value_t params = create_params_from_map(props);

        // 4. 执行查询
        DbClient& db_client = DbClient::getInstance();
        neo4j_result_stream_t* result = db_client.run(cypher_query.c_str(), params);
        
        if (result == NULL) {
            error_message = "Failed to execute CreateEntity query";
            std::cerr << error_message << std::endl;
            return false;
        }

        // 释放结果流
        neo4j_close_results(result);

        std::cout << "Successfully created Entity node with ID: " << entity_node.id() << std::endl;
        return true;

    } catch (const std::exception& e) {
        error_message = "CreateEntity failed: ";
        error_message += e.what();
        std::cerr << error_message << std::endl;
        return false;
    } catch (...) {
        error_message = "CreateEntity failed: Unknown error occurred.";
        std::cerr << error_message << std::endl;
        return false;
    }
}

bool DbCreate::CreateTimeSlot(const ::graph::TimeSlotNode& time_slot_node, std::string& error_message) {
    try {
        // 1. 准备属性参数映射
        std::map<std::string, neo4j_value_t> props;
        props["date"] = create_neo4j_string(time_slot_node.date());
        props["day_of_week"] = create_neo4j_int(time_slot_node.day_of_week());
        props["is_weekend"] = create_neo4j_bool(time_slot_node.is_weekend());
        props["season"] = create_neo4j_string(time_slot_node.season());
        props["holiday_name"] = create_neo4j_string(time_slot_node.holiday_name());

        // 2. 构建 Cypher 查询
        std::ostringstream cypher_oss;
        cypher_oss << "CREATE (n:TimeSlot {";
        bool first = true;
        for (const auto& prop_pair : props) {
            if (!first) cypher_oss << ", ";
            cypher_oss << prop_pair.first << ": $" << prop_pair.first;
            first = false;
        }
        cypher_oss << "}) RETURN n";
        const std::string cypher_query = cypher_oss.str();

        // 3. 创建参数值
        neo4j_value_t params = create_params_from_map(props);

        // 4. 执行查询
        DbClient& db_client = DbClient::getInstance();
        neo4j_result_stream_t* result = db_client.run(cypher_query.c_str(), params);
        
        if (result == NULL) {
            error_message = "Failed to execute CreateTimeSlot query";
            std::cerr << error_message << std::endl;
            return false;
        }

        // 释放结果流
        neo4j_close_results(result);

        std::cout << "Successfully created TimeSlot node for date: " << time_slot_node.date() << std::endl;
        return true;

    } catch (const std::exception& e) {
        error_message = "CreateTimeSlot failed: ";
        error_message += e.what();
        std::cerr << error_message << std::endl;
        return false;
    } catch (...) {
        error_message = "CreateTimeSlot failed: Unknown error occurred.";
        std::cerr << error_message << std::endl;
        return false;
    }
}

bool DbCreate::CreateTrendScore(const ::graph::TrendScoreNode& trend_score_node, std::string& error_message) {
    try {
        // 1. 准备属性参数映射
        std::map<std::string, neo4j_value_t> props;
        props["date"] = create_neo4j_string(trend_score_node.date());
        props["list_id"] = create_neo4j_int(trend_score_node.list_id());
        props["score"] = create_neo4j_float(trend_score_node.score());
        props["rank"] = create_neo4j_int(trend_score_node.rank());
        props["trending_direction"] = create_neo4j_string(trend_score_node.trending_direction());

        // 2. 构建 Cypher 查询
        std::ostringstream cypher_oss;
        cypher_oss << "CREATE (n:TrendScore {";
        bool first = true;
        for (const auto& prop_pair : props) {
            if (!first) cypher_oss << ", ";
            cypher_oss << prop_pair.first << ": $" << prop_pair.first;
            first = false;
        }
        cypher_oss << "}) RETURN n";
        const std::string cypher_query = cypher_oss.str();

        // 3. 创建参数值
        neo4j_value_t params = create_params_from_map(props);

        // 4. 执行查询
        DbClient& db_client = DbClient::getInstance();
        neo4j_result_stream_t* result = db_client.run(cypher_query.c_str(), params);
        
        if (result == NULL) {
            error_message = "Failed to execute CreateTrendScore query";
            std::cerr << error_message << std::endl;
            return false;
        }

        // 释放结果流
        neo4j_close_results(result);

        std::cout << "Successfully created TrendScore node for list ID: " << trend_score_node.list_id() 
                  << " on date: " << trend_score_node.date() << std::endl;
        return true;

    } catch (const std::exception& e) {
        error_message = "CreateTrendScore failed: ";
        error_message += e.what();
        std::cerr << error_message << std::endl;
        return false;
    } catch (...) {
        error_message = "CreateTrendScore failed: Unknown error occurred.";
        std::cerr << error_message << std::endl;
        return false;
    }
}